/**
 * elancom Corporation copy right 2012 - 2015  
 *   
 * $Header: https://192.168.1.224/svn/elancom/product/elancom-platform/trunk/src/main/java/com/elancom/framework/commons/json/parser/deserializer/AbstractDateDeserializer.java 1034 2012-07-02 03:09:12Z lanzhouxue $
 * $Id: AbstractDateDeserializer.java 1034 2012-07-02 03:09:12Z lanzhouxue $
 * $Author: lanzhouxue $
 * $Date: 2012-07-02 11:09:12 +0800 (Mon, 02 Jul 2012) $
 * $Revision: 1034 $
 */
package com.elancom.framework.commons.json.parser.deserializer;

import java.lang.reflect.Type;

import com.elancom.framework.commons.json.JSONException;
import com.elancom.framework.commons.json.parser.DefaultJSONParser;
import com.elancom.framework.commons.json.parser.Feature;
import com.elancom.framework.commons.json.parser.JSONScanner;
import com.elancom.framework.commons.json.parser.JSONToken;

public abstract class AbstractDateDeserializer implements ObjectDeserializer {

	@Override
	@SuppressWarnings("unchecked")
	public <T> T deserialze(DefaultJSONParser parser, Type clazz, Object fieldName) {
		final JSONScanner lexer = (JSONScanner) parser.getLexer();

		Object val;
		if (lexer.token() == JSONToken.LITERAL_INT) {
			val = lexer.longValue();
			lexer.nextToken(JSONToken.COMMA);
		} else if (lexer.token() == JSONToken.LITERAL_STRING) {
			final String strVal = lexer.stringVal();
			val = strVal;
			lexer.nextToken(JSONToken.COMMA);

			if (lexer.isEnabled(Feature.AllowISO8601DateFormat)) {
				final JSONScanner iso8601Lexer = new JSONScanner(strVal);
				if (iso8601Lexer.scanISO8601DateIfMatch()) {
					val = iso8601Lexer.getCalendar().getTime();
				}
			}
		} else if (lexer.token() == JSONToken.NULL) {
			lexer.nextToken();
			val = null;
		} else if (parser.getResolveStatus() == DefaultJSONParser.TypeNameRedirect) {
			parser.accept(JSONToken.COMMA);

			if (lexer.token() == JSONToken.LITERAL_STRING) {
				if (!"val".equals(lexer.stringVal())) {
					throw new JSONException("syntax error");
				}
				lexer.nextToken();
			} else {
				throw new JSONException("syntax error");
			}

			parser.accept(JSONToken.COLON);

			val = parser.parse();

			parser.accept(JSONToken.RBRACE);

			parser.setResolveStatus(DefaultJSONParser.NONE);
		} else {
			val = parser.parse();
		}

		return (T) cast(parser, clazz, fieldName, val);
	}

	protected abstract <T> T cast(DefaultJSONParser parser, Type clazz, Object fieldName, Object value);
}
